package com.unione.map.view.widget

import android.content.Context
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.MotionEvent
import android.view.View
import com.unione.map.R
import com.unione.map.bean.PointInfo
import kotlin.math.sqrt

enum class EnumMapMode {
    MODE_EDIT,
    MODE_NORMAL
}

class MapEditBgView : View {

    companion object {
        const val TAG = "MapEditBgView"
        fun dp2px(dp: Float): Float {
            return TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                dp,
                Resources.getSystem().displayMetrics
            )
        }
    }

    private lateinit var mSquarePaint: Paint
    private lateinit var mMapPaint: Paint
    private var mSquareSize = 8f
    private var mViewWidth: Int = 0
    private var mViewHeight: Int = 0
    private lateinit var mBitmap: Bitmap
    private var mScale = 0f //地图缩放

    private var mOriginScale = 0f //最原始缩放大小 不能比这个更小

    private var mScaleFactor = 0.3f //缩放因子

    private var mTranslateFactor = 0.1f //移动因子
    private var matrix = Matrix()
    private var mMapWidth = 0
    private var mMapHeight = 0
    private var mMapTranslateX = 0f
    private var mMapTranslateY = 0f
    private var mapMode = EnumMapMode.MODE_NORMAL
    private var mIsMapPressed = false
    private var originPointerDistance = 0f
    private var scalePointerDistance = 0f
    private var originPointerX = 0f
    private var newPointerX = 0f
    private var originPointerY = 0f
    private var newPointerY = 0f
    private var mSquareCenterPointList: MutableList<PointInfo> = mutableListOf()


    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet?, def: Int) : super(context, attrs, def) {
        init()
    }

    fun setSquareSize(size: Float) {
        mSquareSize = size
    }

    fun setMapMode(mapMode: EnumMapMode) {
        this.mapMode = mapMode
        invalidate()
    }

    fun getMapMode(): EnumMapMode {
        return mapMode
    }

    private fun init() {
        mSquarePaint = Paint().apply {
            color = Color.WHITE
            strokeJoin = Paint.Join.MITER
            strokeCap = Paint.Cap.BUTT
            isAntiAlias = true
            strokeWidth = dp2px(2f)
            style = Paint.Style.FILL
        }
        mMapPaint = Paint().apply {
            isAntiAlias = true
        }
        mBitmap = BitmapFactory.decodeResource(resources, R.mipmap.map)
        mMapWidth = mBitmap.width
        mMapHeight = mBitmap.height
        Log.i(TAG, "mapWidth:---$mMapWidth,mapHeight:----$mMapHeight")
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mViewWidth = MeasureSpec.getSize(widthMeasureSpec)
        mViewHeight = MeasureSpec.getSize(heightMeasureSpec)
        Log.i(
            TAG,
            "view width height:$mViewWidth $mViewHeight"
        )
        mOriginScale = mViewWidth.toFloat() / mMapWidth.toFloat()
        mScale = mOriginScale
        Log.i(TAG, "缩放比例：$mScale")
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.actionMasked) {
            MotionEvent.ACTION_POINTER_DOWN -> {
                Log.i(TAG, "action pointer down")
                if (mapMode === EnumMapMode.MODE_NORMAL) {
                    if (event.pointerCount == 2) {
                        originPointerDistance = calculatePointerDistance(event)
                    }
                }
            }

            MotionEvent.ACTION_DOWN -> {
                Log.i(TAG, "action down")
                val x = event.x
                val y = event.y
                if (mapMode === EnumMapMode.MODE_NORMAL) {
                    mIsMapPressed = checkIfMapPressed(event)
                    if (mIsMapPressed) {
                        originPointerX = x
                        originPointerY = y
                    }
                } else {
                    // 确定按下中心点
                    addSquareCenterPoint(event)
                }
            }

            MotionEvent.ACTION_MOVE -> {
                Log.i(TAG, "action move")
                if (mapMode === EnumMapMode.MODE_NORMAL) {
                    if (event.pointerCount == 1) {
                        if (mIsMapPressed) {
                            newPointerX = event.x
                            newPointerY = event.y
                            if (checkIfMapVisibleAfterMove()) {
                                mMapTranslateX += (newPointerX - originPointerX) * mTranslateFactor
                                mMapTranslateY += (newPointerY - originPointerY) * mTranslateFactor
                                Log.i(TAG, "地图移动距离x,y分别为：$mMapTranslateX $mMapTranslateY")
                            }
                        }
                    } else if (event.pointerCount == 2) {
                        scalePointerDistance = calculatePointerDistance(event)
                        val scale: Float =
                            mScale + (scalePointerDistance - originPointerDistance) / originPointerDistance * mScaleFactor
                        if (checkIfMapVisibleAfterScale(scale)) {
                            mScale += (scalePointerDistance - originPointerDistance) / originPointerDistance * mScaleFactor
                            mScale = Math.max(mOriginScale, mScale)
                            Log.i(TAG, "缩放比例：$mScale")
                        }
                    }
                }
            }

            MotionEvent.ACTION_UP -> {
                Log.i(TAG, "action up")
                if (mapMode === EnumMapMode.MODE_NORMAL) {
                    mIsMapPressed = false
                } else {

                }
            }

            MotionEvent.ACTION_CANCEL -> Log.i(TAG, "action cancel")
        }
        invalidate()
        return true
    }

    private fun addSquareCenterPoint(event: MotionEvent) {
        val pointInfo = PointInfo()
        // 存储的点位置信息以地图左上角为原点 注意缩放和位移
        pointInfo.drawX = (event.x - mMapTranslateX) / mScale
        pointInfo.drawY = (event.y - mMapTranslateY) / mScale
        pointInfo.squareSize = mSquareSize
        mSquareCenterPointList.add(pointInfo)
    }

    /**
     * 拖动地图最好点在地图上
     *
     * @param event
     * @return
     */
    private fun checkIfMapPressed(event: MotionEvent): Boolean {
        val currentX = event.x
        val currentY = event.y
        val mapLeftX = mMapTranslateX
        val mapTopY = mMapTranslateY
        val mapRightX = mMapTranslateX + mMapWidth * mScale
        val mapBottomY = mMapTranslateY + mMapHeight * mScale
        return currentX > mapLeftX && currentX < mapRightX && currentY > mapTopY && currentY < mapBottomY
    }


    private fun checkIfMapVisibleAfterScale(scale: Float): Boolean {
        val mapLeftX = mMapTranslateX
        val mapTopY = mMapTranslateY
        val mapRightX = mMapTranslateX + mMapWidth * scale
        val mapBottomY = mMapTranslateY + mMapHeight * scale
        return !(mapRightX <= mViewWidth / 2 || mapBottomY <= mViewHeight / 2 || mapLeftX >= mViewWidth / 2 || mapTopY >= mViewHeight / 2)
    }

    private fun checkIfMapVisibleAfterMove(): Boolean {
        val mapLeftX = mMapTranslateX
        val mapTopY = mMapTranslateY
        val mapRightX = mMapTranslateX + mMapWidth * mScale
        val mapBottomY = mMapTranslateY + mMapHeight * mScale
        val currentTranslateX = (newPointerX - originPointerX) * mTranslateFactor
        val currentTranslateY = (newPointerY - originPointerY) * mTranslateFactor
        return !(mapRightX + currentTranslateX <= mViewWidth / 2 || mapBottomY + currentTranslateY <= mViewHeight / 2 || mapLeftX + currentTranslateX >= mViewWidth / 2 || mapTopY + currentTranslateY >= mViewHeight / 2)
    }


    private fun calculatePointerDistance(event: MotionEvent): Float {
        val x1 = event.getX(0)
        val x2 = event.getX(1)
        val y1 = event.getY(0)
        val y2 = event.getY(1)
        return sqrt(((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)).toDouble()).toFloat()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        matrix.reset()
        matrix.postScale(mScale, mScale)
        matrix.postTranslate(mMapTranslateX, mMapTranslateY)
        canvas.drawBitmap(mBitmap, matrix, mMapPaint)
        drawSquares(canvas)
    }

    fun clearAllSquares() {
        mSquareCenterPointList.clear()
        invalidate()
    }

    private fun drawSquares(canvas: Canvas) {
        for (pointInfo in mSquareCenterPointList) {
            canvas.drawRect(
                RectF(
                    getSquareRealLeft(pointInfo), getSquareRealTop(pointInfo),
                    getSquareRealRight(pointInfo), getSquareRealBottom(pointInfo)
                ), mSquarePaint
            )
        }
    }

    fun getSquareRealLeft(pointInfo: PointInfo): Float {
        val centerPointX = pointInfo.drawX * mScale + mMapTranslateX
        return centerPointX - pointInfo.squareSize / 2
    }

    fun getSquareRealRight(pointInfo: PointInfo): Float {
        val centerPointX = pointInfo.drawX * mScale + mMapTranslateX
        return centerPointX + pointInfo.squareSize / 2
    }

    fun getSquareRealTop(pointInfo: PointInfo): Float {
        val centerPointY = pointInfo.drawY * mScale + mMapTranslateY
        return centerPointY - pointInfo.squareSize / 2
    }

    fun getSquareRealBottom(pointInfo: PointInfo): Float {
        val centerPointY = pointInfo.drawY * mScale + mMapTranslateY
        return centerPointY + pointInfo.squareSize / 2
    }

}

